﻿#pragma once
#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//#include <stdlib.h>
//#include <windows.h>

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>		 // 字符串流
#include <vector>		 // 动态数组
#include <memory>		 // 内存管理
#include <unordered_map> // 哈希表（类似于 python 的字典）
#include <functional>	 // 函数对象
#include <future>		 // 异步编程
#include <thread>		 // 线程库
//#include <chrono>		 // 时间库
//#include <mutex>		 // 互斥锁
//#include <algorithm>	 // 算法库

// 图形库 GLFW、GLEW
#include <glew.h> // GLEW Library, glew.h 的包含必须在 GLFW 库之前
#include <wglew.h>
//#include <eglew.h>
//#include <glxew.h>
#include <glfw3.h>
#include <glfw3native.h>

// 数学库 glm 
#define GL_GLEXT_PROTOTYPES
#define GLM_ENABLE_EXPERIMENTAL		// transform.hpp 包含实验性的矩阵变换函数需要定义的宏
#include <glm/glm.hpp>					// GLM Library
#include <glm/gtc/matrix_transform.hpp> // 矩阵变换
#include <glm/gtx/transform.hpp>
//#include <gtx/string_cast.hpp>		// 字符串转化为 glm 类型

// 图型界面库 imgui 
#define GL_SILENCE_DEPRECATION
#include <imgui/imgui.h>
#include <imgui/imgui_impl_glfw.h>
#include <imgui/imgui_impl_opengl3.h>

using std::cout;
using std::endl;

extern void gl_clean_error();
extern bool gl_check_error(const char* file, const char* function, int line);
#define gl_assert(expr) if (!(expr)) __debugbreak();  // 断点调试宏定义，__debugbreak 是 MSVC 编译器特有的调试断点指令，其他 __ 前缀的函数(非预处理指令)也一样
#define gl_call(func) gl_clean_error();	/*调用 gl_call 影响性能，建议只在调试时使用*/\
	func;\
	gl_assert(gl_check_error(#func, __FILE__, __LINE__))	// 检查 OpenGL 错误的宏定义，__FILE__ 和 __LINE__ 是预处理器定义，表示当前文件名和调用函数的行号，这里小注意：func 中不能有 if 等语句，否则不会调用 gl_check_error 函数

// 抽象 ImGui 类
class MyImGui
{
private:
	ImVec4 clear_color;	  // 设置窗口背景色
	ImGuiIO& io;
	ImGuiStyle& style;

	static ImGuiIO& init_io();  // 使用别人的单例
public:
	MyImGui() = delete; // 禁止默认构造函数
	MyImGui(float red, float green, float blue, float alpha);
	~MyImGui();

	void set_up(GLFWwindow* window, const char* version);

	void new_frame();

	void render(GLFWwindow* window);

	/*void shutdown(); */

	ImVec4& get_clear_color();
	ImGuiIO& get_io();
	ImGuiStyle& get_style();
};